package xcmg.device.service.split;

import com.github.pagehelper.PageInfo;
import yb.ecp.fast.infra.util.PageHelperPlus;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.PriMaterialsDO;
import xcmg.device.dao.entity.barcode.BarcodeManageDO;
import xcmg.device.dao.entity.split.RestoreDO;
import xcmg.device.dao.entity.split.RestoreDetailDO;
import xcmg.device.dao.entity.split.SplitDO;
import xcmg.device.dao.entity.split.SplitDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseInventoryDO;
import xcmg.device.dao.mapper.BarcodeManageMapper;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.split.RestoreDetailMapper;
import xcmg.device.dao.mapper.split.RestoreMapper;
import xcmg.device.dao.mapper.split.SplitDetailMapper;
import xcmg.device.dao.mapper.split.SplitMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.vo.split.RestoreAddVO;
import xcmg.device.service.vo.split.RestoreDetailVO;
import xcmg.device.service.vo.split.RestoreNumVO;
import xcmg.device.service.vo.split.RestorePdaVO;
import xcmg.device.service.vo.split.RestoreVO;
import xcmg.device.service.vo.split.SplitAddVO;
import xcmg.device.service.vo.split.SplitDetailVO;
import xcmg.device.service.vo.split.SplitVO;
import xcmg.device.service.warehouse.CommonService;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class RestoreService {

    @Autowired
    private RestoreMapper restoreMapper;

    @Autowired
    private RestoreDetailMapper restoreDetailMapper;

    @Autowired
    private SplitMapper splitMapper;

    @Autowired
    private SplitDetailMapper splitDetailMapper;

    @Autowired
    private BarcodeManageMapper barcodeManageMapper;

    @Autowired
    private PriMaterialsMapper priMaterialsMapper;

    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private HttpServletResponse response;

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode add(SplitAddVO splitAddVO)throws Exception{
        if(splitAddVO.getHeaderInfo() == null || ListUtil.isNullOrEmpty(splitAddVO.getMaterialList())){
            return ErrorCode.IllegalArument;
        }
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return ErrorCode.IllegalArument;
        }

        SplitVO splitVO = splitAddVO.getHeaderInfo();
        RestoreDO restoreDO = new RestoreDO();
        BeanUtils.copyProperties(splitVO, restoreDO);
        restoreDO.setId(textResult.getValue());
        restoreDO.setRestoreOrder(genDocumentService.getDocumentNo(BillDesc.CMRestore));
        restoreDO.setAmount(BigDecimal.ZERO);
        restoreDO.setCreateDate(new Date());
        boolean success;

        for(SplitDetailVO detailVO : splitAddVO.getMaterialList()){
            if(detailVO.getMatType() == 0){
                restoreDO.setAmount(restoreDO.getAmount().add(detailVO.getAmount()));
            }
        }
        success = restoreMapper.insert(restoreDO)>0;
        if(!success){
            throw new Exception("操作失败");
        }
        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean addDetail(String splitOrder, String barcode, String userId, String orgId)throws Exception{
        RestoreDO restoreDO = restoreMapper.selectBySplitOrder(splitOrder, orgId);
        if(restoreDO == null){
            throw new Exception("未找到拆件恢复单");
        }
        BarcodeManageDO barcodeManageDO = barcodeManageMapper.item(barcode, orgId);
        if(barcodeManageDO == null){
            throw new Exception("未找到原件条码");
        }
        if(!"1".equals(barcodeManageDO.getBarcodeStatus())){
            throw new Exception("原件条码不是已入库状态");
        }
        PriMaterialsDO materialsDO = priMaterialsMapper.itemByNo(barcodeManageDO.getMaterialsNo(), orgId);
        if(materialsDO == null){
            throw new Exception("未找到零件");
        }
        RestoreDetailDO restoreDetailDO = restoreDetailMapper.selectByBarcode(restoreDO.getId(), barcode);
        if(restoreDetailDO == null){
            restoreDetailDO = new RestoreDetailDO();
            BeanUtils.copyProperties(materialsDO, restoreDetailDO);
            restoreDetailDO.setId(fastGenClient.textGuid().getValue());
            restoreDetailDO.setMainId(restoreDO.getId());
            restoreDetailDO.setBarcode(barcode);
            restoreDetailDO.setAmount(barcodeManageDO.getCurrentQty());
            restoreDetailDO.setCreateId(userId);
            restoreDetailDO.setCreateName(commonService.getUserName(userId));
            restoreDetailDO.setCreateDate(new Date());
            boolean success = restoreDetailMapper.insert(restoreDetailDO)>0;
            if(!success){
                throw new Exception("新增拆件恢复记录失败");
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode restorePda(RestorePdaVO restorePdaVO, String userId, String orgId)throws Exception{
        RestoreDO restoreDO = restoreMapper.selectByRestoreOrder(restorePdaVO.getRestoreOrder(), orgId);
        if(restoreDO == null){
            throw new Exception("未找到拆件恢复单");
        }
        RestoreDetailDO restoreDetailDO = restoreDetailMapper.selectByBarcode(restoreDO.getId(), restorePdaVO.getBarcode());
        if(restoreDetailDO == null){
            throw new Exception("未找到拆件恢复记录");
        }
        WarehouseInventoryDO warehouseInventoryDO = warehouseInventoryMapper.selectByBarCode(restorePdaVO.getBarcode(), orgId);
        if(warehouseInventoryDO == null){
            throw new Exception("未根据条码找到库存记录");
        }
        if(warehouseInventoryDO.getStatus() != 1){
            throw new Exception("当前条码不是冻结状态");
        }
        restoreDetailDO.setRestoreStatus(1);
        restoreDetailDO.setRestoreId(userId);
        restoreDetailDO.setRestoreName(commonService.getUserName(userId));
        restoreDetailDO.setRestoreDate(new Date());
        boolean success = restoreDetailMapper.update(restoreDetailDO)>0;
        if(!success){
            throw new Exception("更新拆件恢复记录失败");
        }

        restoreDO.setRestoreAmount(restoreDO.getRestoreAmount().add(restoreDetailDO.getAmount()));
        if(restoreDO.getAmount().compareTo(restoreDO.getRestoreAmount()) < 0){
            throw new Exception("已恢复数量不能大于计划恢复数量");
        }else if(restoreDO.getAmount().compareTo(restoreDO.getRestoreAmount()) == 0){
            restoreDO.setRestoreStatus(2);
        }else{
            restoreDO.setRestoreStatus(1);
        }
        success = restoreMapper.update(restoreDO)>0;
        if(!success){
            throw new Exception("更新拆件恢复单失败");
        }

        //更新拆件单原件恢复状态
        SplitDO splitDO = splitMapper.selectBySplitOrder(restoreDO.getSplitOrder(), orgId);
        if(splitDO == null){
            throw new Exception("未找到拆件单");
        }
        SplitDetailDO splitDetailDO = splitDetailMapper.selectByMaterialNo(splitDO.getId(), 0, restoreDetailDO.getMaterialsNo());
        if(splitDetailDO == null){
            throw new Exception("未找到拆件单中原件记录");
        }
        splitDetailDO.setRestoreAmount(splitDetailDO.getRestoreAmount().add(restoreDetailDO.getAmount()));
        if(splitDetailDO.getRestoreAmount().compareTo(splitDetailDO.getAmount()) > 0){
            throw new Exception("拆件单中原件已恢复数量不能大于计划恢复数量");
        }else if(splitDetailDO.getRestoreAmount().compareTo(splitDetailDO.getAmount()) == 0){
            splitDO.setRestoreStatus(2);
        }else{
            splitDO.setRestoreStatus(1);
        }
        success = splitDetailMapper.update(splitDetailDO)>0;
        if(!success){
            throw new Exception("更新拆件单中原件已恢复数量失败");
        }
        success = splitMapper.update(splitDO)>0;
        if(!success){
            throw new Exception("更新拆件单中原件恢复状态失败");
        }

        //解除库存记录的解冻状态
        warehouseInventoryDO.setStatus(0);
        success = warehouseInventoryMapper.updateByPrimaryKeySelective(warehouseInventoryDO)>0;
        if(!success){
            throw new Exception("更新库存状态失败");
        }
        return ErrorCode.Success;
    }

    public PageCommonVO list(SearchCommonVO<RestoreVO> condition) {
        PageCommonVO<RestoreVO> pageCommonVO = new PageCommonVO();
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<RestoreDO> doList = restoreMapper.list(condition.getFilters());
        List<RestoreVO> voList = new ArrayList<>();
        for (RestoreDO entity : doList) {
            RestoreVO model = new RestoreVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        pageCommonVO.setPageInfo(new PageInfo(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    public RestoreAddVO item(String id){
        RestoreAddVO result = new RestoreAddVO();
        RestoreDO restoreDO = restoreMapper.selectByPrimaryKey(id);
        if(restoreDO == null){
            return result;
        }
        RestoreVO restoreVO = new RestoreVO();
        BeanUtils.copyProperties(restoreDO, restoreVO);
        result.setHeaderInfo(restoreVO);
        List<RestoreDetailVO> listVO = new ArrayList<>();
        List<RestoreDetailDO> listDO = restoreDetailMapper.list(id);
        for(RestoreDetailDO entity:listDO){
            RestoreDetailVO model = new RestoreDetailVO();
            BeanUtils.copyProperties(entity, model);
            model.setRestoreStatusStr(model.getRestoreStatus()==0?"未恢复":"已恢复");
            model.setRestoreDateStr(DateUtil.formatDateTime(model.getRestoreDate()));
            listVO.add(model);
        }
        result.setMaterialList(listVO);
        return result;
    }

    public void export(List<String> ids)throws Exception{
        PageHelperPlus.orderBy("create_date desc");
        invokeExport(restoreMapper.findByIds(ids));
    }

    public void exportAll(RestoreVO condition)throws Exception{
        Integer count = restoreMapper.listCount(condition);
        List<RestoreDO> dataList = new ArrayList<>();
        int times = count/500+1;
        for(int i=0; i<times; i++){
            PageHelperPlus.startPage(i + 1, 500, "create_date desc");
            dataList.addAll(restoreMapper.list(condition));
        }
        invokeExport(dataList);
    }

    private void invokeExport(List<RestoreDO> doList)throws Exception{
        String title = "拆件恢复单数据导出";
        String[] rowsName = new String[]{"序号","拆件恢复单号","拆件单号","总数量","已恢复数量","恢复状态",
                "创建人", "创建时间"};
        List<Object[]>  dataList = new ArrayList<>();
        Object[] objs;
        for (int i = 0; i < doList.size(); i++) {
            RestoreDO exportDO = doList.get(i);
            objs = new Object[rowsName.length];
            objs[0] = i+1;
            objs[1] = exportDO.getRestoreOrder();
            objs[2] = exportDO.getSplitOrder();
            objs[3] = exportDO.getAmount();
            objs[4] = exportDO.getRestoreAmount();
            objs[5] = getRestoreState(exportDO.getRestoreStatus());
            objs[6] = exportDO.getCreateName();
            objs[7] = DateUtil.formatDateTime(exportDO.getCreateDate());
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getRestoreState(Integer state){
        switch (state){
            case 0:
                return "未恢复";
            case 1:
                return "部分恢复";
            case 2:
                return "已恢复";
            default:
                return "未恢复";
        }
    }

    public RestoreNumVO getRestoreAmount(String restoreOrder, String orgId){
        RestoreNumVO restoreNumVO = new RestoreNumVO();
        RestoreDO restoreDO = restoreMapper.selectByRestoreOrder(restoreOrder, orgId);
        if(restoreDO == null){
            return restoreNumVO;
        }
        restoreNumVO.setRestoreNum(restoreDO.getRestoreAmount());
        restoreNumVO.setNotRestoreNum(restoreDO.getAmount().subtract(restoreDO.getRestoreAmount()));
        return restoreNumVO;
    }

    public List<RestoreDetailDO> listByStatus(String restoreOrder, Integer type, String orgId){
        RestoreDO restoreDO = restoreMapper.selectByRestoreOrder(restoreOrder, orgId);
        if(restoreDO == null){
            return new ArrayList<>();
        }
        return restoreDetailMapper.selectByRestoreStatus(restoreDO.getId(), type);
    }
}
